package com.github.dengmin.mysql.service;

import com.github.dengmin.mysql.dao.RoleDao;
import com.github.dengmin.mysql.model.Role;
import com.github.dengmin.mysql.model.User;
import com.github.dengmin.mysql.shiro.cache.LoginRedisService;
import com.github.dengmin.mysql.shiro.jwt.JwtProperties;
import com.github.dengmin.mysql.shiro.jwt.JwtToken;
import com.github.dengmin.mysql.shiro.jwt.JwtUtil;
import com.github.dengmin.mysql.shiro.vo.LoginUserVo;
import com.github.dengmin.mysql.utils.BCrypt;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;

/**
 * @Author dengmin
 * @Created 2020/8/17 下午2:36
 */
@Slf4j
@Service
public class LoginService {
    private static final long serialVersionUID = 1L;

    @Lazy
    @Autowired
    private JwtProperties jwtProperties;

    @Resource
    private UserService userService;
    @Resource
    private RoleDao roleDao;

    @Lazy
    @Autowired
    private LoginRedisService loginRedisService;

    public String login(String username, String password) throws Exception{
        User user = userService.getByName(username);
        if(null == user){
            throw new AuthenticationException("用户名或密码错误");
        }

        if(!BCrypt.checkpw(password, user.getPassword())){
            throw new AuthenticationException("用户名或密码错误");
        }
        //用户角色
        Role role = roleDao.getById(user.getRoleId());
        LoginUserVo loginUserVo = new LoginUserVo();
        BeanUtils.copyProperties(user, loginUserVo);
        loginUserVo.setRoleName(role.getName());
        loginUserVo.setRoleCode(role.getCode());

        String salt = user.getSalt();
        //查询角色和权限
        if(StringUtils.isBlank(salt)){
            salt = BCrypt.gensalt();
        }
        Long expireSecond = jwtProperties.getExpireSecond();
        String token = JwtUtil.generateToken(username, salt, Duration.ofSeconds(expireSecond));

        JwtToken jwtToken = JwtToken.build(token, username, salt, expireSecond);
        Subject subject = SecurityUtils.getSubject();
        subject.login(jwtToken);
        loginRedisService.cacheLoginInfo(jwtToken, loginUserVo);
        return token;
    }

    public void logout(HttpServletRequest request) throws Exception{
        Subject subject = SecurityUtils.getSubject();
        subject.logout();

        String token = JwtUtil.getToken(request);
        String username = JwtUtil.getUsername(token);

        loginRedisService.deleteLoginInfo(token, username);
    }

}
